package com.example.stock.annotation.handler;

import com.example.stock.annotation.TokenToUser;
import com.example.stock.common.Constants;
import com.example.stock.entity.User;
import com.example.stock.entity.UserToken;
import com.example.stock.service.UserService;
import com.example.stock.util.LoginUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@Log4j2
@Component
public class TokenToUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    UserService userService;

    /**
     * 重写的方法，用于判断是否支持给定的MethodParameter参数
     * @param parameter MethodParameter对象，表示要判断的参数
     * @return 如果参数具有TokenToUser注解，则返回true，否则返回false
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.hasParameterAnnotation(TokenToUser.class)) {
            return true;
        }
        return false;
    }

    /**
     * 解析方法参数，返回解析后的对象
     *
     * @param parameter           方法参数
     * @param mavContainer        ModelAndViewContainer对象
     * @param webRequest          NativeWebRequest对象
     * @param binderFactory       WebDataBinderFactory对象
     * @return 解析后的对象
     * @throws Exception          如果解析过程中发生异常，则抛出异常
     */
    @Override
    public User resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        LoginUtil.clearLoginUser();

        // 如果方法参数含有TokenToUser注解
        if (parameter.getParameterAnnotation(TokenToUser.class) != null) {
            User user = null;

            // 从请求头中获取token
            String token = webRequest.getHeader("token");

            // 如果token不为空且长度为常量 Constants.TOKEN_LENGTH
            if (null != token && token.length() == Constants.TOKEN_LENGTH) {

                // 通过token查询用户信息
                UserToken userToken = userService.selectUserTokenByToken(token);

                // 如果用户Token为空或过期，则抛出异常
                if (userToken == null || userToken.getExpireTime().getTime() <= System.currentTimeMillis()) {
                    //StockException.fail(ServiceResultEnum.TOKEN_EXPIRE_ERROR.getResult());
                    return null;
                }

                // 查询用户信息
                user = userService.selectUserByPrimaryKey(userToken.getUserId());
                // 如果用户为空，则抛出异常
                if (user == null) {
                    //StockException.fail(ServiceResultEnum.USER_NULL_ERROR.getResult());
                    return null;
                }

                // 如果用户被锁定，则抛出异常
                if (user.getLockedFlag().intValue() == 1) {
                    //StockException.fail(ServiceResultEnum.LOGIN_USER_LOCKED_ERROR.getResult());
                    return null;
                }

                log.info("user: " + user);
                LoginUtil.setLoginUser(user);
                // 返回解析后的用户对象
                return user;
            } else {
                // 如果token为空，则抛出异常
                //StockException.fail(ServiceResultEnum.NOT_LOGIN_ERROR.getResult());
                return null;
            }
        }

        // 如果方法参数不含有TokenToUser注解，则返回null
        return null;
    }

}
